/*
 * @(#)MaintUserRoleAction.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.workflow.web;

import java.sql.Connection;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.quartz.SchedulerException;

import com.dcivision.dms.bean.DmsDocument;
import com.dcivision.dms.core.DocumentRetrievalManager;
import com.dcivision.dms.dao.DmsDocumentDAObject;
import com.dcivision.dms.dao.DmsRootDAObject;
import com.dcivision.form.bean.FormRecord;
import com.dcivision.form.dao.FormGroupDAObject;
import com.dcivision.form.dao.FormRecordDAObject;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ApplicationExceptionList;
import com.dcivision.framework.ApplicationMessageList;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.PermissionManager;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemFunctionConstant;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.framework.dao.SysUserDefinedIndexDAObject;
import com.dcivision.framework.web.AbstractActionForm;
import com.dcivision.framework.web.AbstractMaintAction;
import com.dcivision.setup.dao.SetupOptionWorkflowCategoryDAObject;
import com.dcivision.workflow.WorkflowErrorConstant;
import com.dcivision.workflow.bean.MtmWorkflowInterruptUserActor;
import com.dcivision.workflow.bean.MtmWorkflowRecordObjectLink;
import com.dcivision.workflow.bean.MtmWorkflowStepUserActor;
import com.dcivision.workflow.bean.MtmWorkflowStepWorkflowStep;
import com.dcivision.workflow.bean.WorkflowGroup;
import com.dcivision.workflow.bean.WorkflowRecord;
import com.dcivision.workflow.bean.WorkflowScheduleTriggers;
import com.dcivision.workflow.bean.WorkflowStep;
import com.dcivision.workflow.core.SystemWorkflowConstant;
import com.dcivision.workflow.core.WorkflowOperationManager;
import com.dcivision.workflow.core.WorkflowStepManager;
import com.dcivision.workflow.core.WorkflowStepOperationWarningMessageManager;
import com.dcivision.workflow.dao.MtmWorkflowInterruptUserActorDAObject;
import com.dcivision.workflow.dao.MtmWorkflowRecordObjectLinkDAObject;
import com.dcivision.workflow.dao.MtmWorkflowStepUserActorDAObject;
import com.dcivision.workflow.dao.MtmWorkflowStepWorkflowStepDAObject;
import com.dcivision.workflow.dao.WorkflowGroupDAObject;
import com.dcivision.workflow.dao.WorkflowRecordDAObject;
import com.dcivision.workflow.dao.WorkflowScheduleTriggersDAObject;
import com.dcivision.workflow.dao.WorkflowStepDAObject;

/**
  MaintWorkflowRecordAction.java

  This class is for maint wprkflow record.

    @author          Angus Shiu
    @company         DCIVision Limited
    @creation date   29/07/2003
    @version         $Revision: 1.61.2.7 $
*/
public class MaintWorkflowRecordAction extends AbstractMaintAction {

  public static final String REVISION = "$Revision: 1.61.2.7 $";

  public static final String VAR_ACCESSIBLE_GROUP_LIST = "accessibleGroupList";
  /** Creates a new instance of MaintWorkflowRecordAction */
  public MaintWorkflowRecordAction() {
    super();
  }

  /** getFunctionCode
   *
   * Abstract function which sub-class should implement to return the corresponding
   * function code.
   *
   * @return   The function code
   */
  public String getFunctionCode() {
    return(SystemFunctionConstant.WORKFLOW_RECORD);
  }

  /** getMajorDAOClassName
   *
   * Abstract function which sub-class should implement to return the corresponding
   * major DAO class name used in this class.
   *
   * @return   The DAO class name
   */
  public String getMajorDAOClassName() {
    return("com.dcivision.workflow.dao.WorkflowRecordDAObject");
  }

  /**
   * setPageTitle
   * set the extend page title and page path.
   * default page path/title will be created by navmode and functionCode
   */
  public void setPageTitle(HttpServletRequest request, HttpServletResponse response, ActionForm form, ActionMapping mapping, ActionForward actionForward){
    WorkflowGroup currentGroup = (WorkflowGroup)request.getAttribute("workflowGroup");
    StringBuffer extendPath = new StringBuffer("<a href=\"ListWorkflowRecord.do?workflowGroupID="+currentGroup.getID()+"&opMode="+GlobalConstant.OP_MODE_LIST_RETAIN+"\">");
    extendPath.append(currentGroup.getGroupName());
    extendPath.append("</a>");
    request.setAttribute(GlobalConstant.EXTEND_PAGE_PATH, extendPath.toString());
  }
  
  public void clearUniqueFields(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    MaintWorkflowRecordForm workflowRecordForm = (MaintWorkflowRecordForm) form;
    workflowRecordForm.setID(null);
    workflowRecordForm.setWorkflowVersion(null);
    workflowRecordForm.setStatus(GlobalConstant.RECORD_PENDING);
    //workflowRecordForm.setDescription(null);TC.delete for BUG
  }

  public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws ServletException,ApplicationException {
	  ActionForward retValue;
    SessionContainer sessionContainer = (SessionContainer) request.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);
    PermissionManager permissionManager = sessionContainer.getPermissionManager();
    WorkflowOperationManager wfOperationManager = new WorkflowOperationManager(sessionContainer,this.getConnection(request));

    MaintWorkflowRecordForm maintForm = (MaintWorkflowRecordForm) form;
    //simon_add_start
    Connection conn = this.getConnection(request);
    WorkflowGroupDAObject wfGroupDAO = new WorkflowGroupDAObject(sessionContainer, conn);
    String wfGroupID=maintForm.getWorkflowGroupID();
    if(wfGroupID==null){
      wfGroupID=request.getParameter("wfGroupID");
    }
    if(wfGroupID!=null){
      WorkflowGroup wfGroup = (WorkflowGroup) wfGroupDAO.getObjectByID(TextUtility.parseIntegerObj(wfGroupID));
      request.setAttribute("workflowGroup", wfGroup);
    }
    //simon_add_end
    
    //handle the End Date is not Empty
    if(!Utility.isEmpty(maintForm.getEndDate()) ){
      Timestamp endDateTimestamp = Utility.parseDateStringToSystemDate(maintForm.getEndDate(), SystemParameterFactory.getSystemParameter(SystemParameterConstant.DB_DATETIME_FORMAT));
      Calendar endDateCal = Utility.timestampToCalendar(endDateTimestamp);
      endDateCal.set(Calendar.HOUR_OF_DAY, 23);
      endDateCal.set(Calendar.MINUTE, 59);
      endDateCal.set(Calendar.SECOND, 59);
      endDateCal.set(Calendar.MILLISECOND, 0);
      endDateTimestamp = Utility.calendarToTimestamp(endDateCal);
      maintForm.setEndDate(endDateTimestamp.toString());
    }
    
    String opMode = (maintForm!=null) ? maintForm.getOpMode() : request.getParameter("opMode");    //maintForm.getOpMode();
    String navMode = (maintForm!=null) ? maintForm.getNavMode() : request.getParameter("navMode"); //maintForm.getNavMode();
    String operationType = request.getParameter("operationType");

    //check whether the request come form applet
    String fromType = request.getParameter("fromType");
    log.debug( ((maintForm!=null) ? maintForm.getClass().getName() : "")+", OP Mode:"+opMode+", Nav Mode:"+navMode);

    // Set the function code for current action.
    ActionForward forward = this.retrieveFunctionCode(request, response, mapping);  if (forward!=null) {return forward;}

    Hashtable hAccessibleGroup = permissionManager.getAccessibleObjectHash(GlobalConstant.OBJECT_TYPE_WORKFLOW);
    Set keySet = hAccessibleGroup.keySet();
    String sAccessibleGroup = "-1";
    for (Iterator iter=keySet.iterator(); iter.hasNext(); ) {
      Integer workflowGroupID = (Integer) iter.next();
      String sPermission = (String) hAccessibleGroup.get(workflowGroupID);
      if (sPermission.equals(sPermission.toUpperCase())) {
        sAccessibleGroup = sAccessibleGroup + ", " + workflowGroupID;
      }
    }
    request.setAttribute(VAR_ACCESSIBLE_GROUP_LIST, sAccessibleGroup);
    // get interrupt workflow

    List interruptWorkflowRecordList = new ArrayList();
    interruptWorkflowRecordList = this.getWorkflowRecordBySysWorkflowCategoryID(new Integer(SystemWorkflowConstant.SUB_WORKFLOW_INTERRUPT), request);
    request.setAttribute("InterruptWorkflowRecordList", interruptWorkflowRecordList);

    // Delete Single Step
    if(!Utility.isEmpty(operationType) && WorkflowStep.OPERATION_TYPE_DELETE_SINGLE_STEP.equals(operationType)){
      //tc.update start.should catch the exception here
      try{
        this.deleteStep(maintForm, request, false);
      }catch(ApplicationException appEx){
        this.rollback(request);
        handleApplicationException(request, appEx);
      }
      //tc.update end
      
      retValue = super.execute(mapping, maintForm, request, response);
      this.commit(request);
      refreshFormData(mapping, maintForm, request, response);
      return retValue;

    // Delete All Step After
    }else if(!Utility.isEmpty(operationType) && WorkflowStep.OPERATION_TYPE_DELETE_ALL_STEP.equals(operationType)){
      try{
        this.deleteStep(maintForm, request, true);
      }catch(ApplicationException appEx){
        this.rollback(request);
        handleApplicationException(request, appEx); 
      }
      
      retValue = super.execute(mapping, maintForm, request, response);
      this.commit(request);
      refreshFormData(mapping, maintForm, request, response);
      return retValue;
    }
    
    if (!GlobalConstant.NAV_MODE_REFRESH.equals(opMode)) {
      if (!Utility.isEmpty(opMode) &&
            (GlobalConstant.OP_MODE_INSERT.equals(opMode) ||
              GlobalConstant.OP_MODE_INSERT_NEW.equals(opMode) ||
              GlobalConstant.OP_MODE_UPDATE.equals(opMode) ||
              GlobalConstant.OP_MODE_UPDATE_NEW.equals(opMode) ||
              GlobalConstant.OP_MODE_COPY.equals(opMode) )
         ) {
    	  //bill add for EIP-1183 start
    	  try{
    		  this.checkDueDate(sessionContainer,conn,form);
    	  }catch(ApplicationException appEx){
    		  handleApplicationException(request, appEx);
    		  maintForm.setNavMode(GlobalConstant.NAV_MODE_EDIT);
    	      return mapping.findForward(GlobalConstant.NAV_MODE_EDIT);
    	  }
    	  //bill add for EIP-1183 end
          retValue = super.execute(mapping, form, request, response);
          if (!isError(request) &&  GlobalConstant.RECORD_PENDING.equals(maintForm.getStatus()) ) {        	
            maintForm.setNavMode(GlobalConstant.NAV_MODE_EDIT);            
            retValue = mapping.findForward(GlobalConstant.NAV_MODE_EDIT);
            
          }               
          if(isError(request) && Utility.isEmpty(maintForm.getRecordStatus())){
        	  maintForm.setStatus(GlobalConstant.RECORD_PENDING);
          }
      } else {
        retValue = super.execute(mapping, form, request, response);
      }
      refreshFormData(mapping, maintForm, request, response);
    } else {
      try {
        refreshFormData(mapping, maintForm, request, response);
      } catch (ApplicationException appEx) {
        this.rollback(request);
        handleApplicationException(request, appEx);
      }
      if(WorkflowRecord.REQUEST_COME_FROM_APPLET.equals(fromType)){//if request come from applet,sendRedirect to applet
        return mapping.findForward(WorkflowRecord.REQUEST_COME_FROM_APPLET);
      }
      if (isError(request)) {
        maintForm.setNavMode(GlobalConstant.NAV_MODE_EDIT);
        return mapping.findForward(GlobalConstant.NAV_MODE_EDIT);
      } else {
        return mapping.findForward(GlobalConstant.NAV_MODE_REFRESH);
      }
    }
    if(WorkflowRecord.REQUEST_COME_FROM_APPLET.equals(fromType)){//if request come from applet,sendRedirect to applet
      return mapping.findForward(WorkflowRecord.REQUEST_COME_FROM_APPLET);
    } else{
      return retValue;
    }
  }
  /**checkDueDate
   * 
   * Check with the due date when save and release
   * 
   * @author bill
   * @param sessionContainer
   * @param conn
   * @param workflowRecordForm
   * @throws ApplicationException
   */
   public void checkDueDate(SessionContainer sessionContainer,Connection conn,ActionForm workflowRecordForm)throws ApplicationException{
	 AbstractActionForm workflowRecordMaintForm = (AbstractActionForm)workflowRecordForm;
	 WorkflowRecord workflowRecord = (WorkflowRecord) workflowRecordMaintForm.getFormData();
	 WorkflowStepDAObject wfStepDAO=new WorkflowStepDAObject(sessionContainer,conn);
	 List stepList=wfStepDAO.getListByWorkflowRecordID(workflowRecord.getID());
	 for(int index=0;index<stepList.size();index++){
	    WorkflowStep tmpWorkflowStep=(WorkflowStep)stepList.get(index);
	    if(!Utility.isEmpty(tmpWorkflowStep.getOnNoResponseAfter())){
	    //Due date can't be less than current date
	    	if (Utility.timestampToCalendar(tmpWorkflowStep.getOnNoResponseAfter()).before(Utility.timestampToCalendar(Utility.getCurrentTimestamp())) ){
	    		throw new ApplicationException(ErrorConstant.WORKFLOW_DUE_DATE_CANNOT_BE_LESS_THAN_CURRENT_DATE);
	      	 }
	     }
	  }
  }
  public void insertRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    WorkflowOperationManager workflowOperationManager = new WorkflowOperationManager(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStepManager wsManager=new WorkflowStepManager(this.getSessionContainer(request), this.getConnection(request));
    WorkflowRecord bean = workflowOperationManager.createWorkflowRecord((WorkflowRecord)form.getFormData());
    form.setFormData(bean);
    MaintWorkflowRecordForm maintForm = (MaintWorkflowRecordForm) form;
    String[] categoryObjectID = maintForm.getCategoryObjectID();
    String[] rule = maintForm.getRule();

    WorkflowRecord workflowRecord = (WorkflowRecord) form.getFormData();
    this.updateWorkflowRecordObjectLink(workflowRecord.getID(), workflowRecord.getWorkflowCategoryID(), categoryObjectID, rule, request);

    // insert sub workflow for interruption header workflow is submitter(s)
    if (!Utility.isEmpty(maintForm.getInterruptSubmitter())) {
      wsManager.deleteWFInterruptUserActorByRecordID(bean.getID());
    }
    this.insertInterruptWorkflowSubmitter(request, maintForm, bean.getID());

  }

  public void copyRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {

    WorkflowOperationManager workflowOperationManager = new WorkflowOperationManager(this.getSessionContainer(request), this.getConnection(request));
    WorkflowRecord bean = workflowOperationManager.copyWorkflowRecord((WorkflowRecord)form.getFormData(), GlobalConstant.TRUE.equals( ((MaintWorkflowRecordForm)form).getCopyAllSteps() ) );
    form.setFormData(bean);
    // after copy source record, update user modify current record option
    this.updateRecord(mapping, form, request, response);
  }

  public void updateRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    MaintWorkflowRecordForm maintForm = (MaintWorkflowRecordForm) form;
    WorkflowStepManager wsManager=new WorkflowStepManager(this.getSessionContainer(request), this.getConnection(request));
    String[] categoryObjectID = maintForm.getCategoryObjectID();
    String[] rule = maintForm.getRule();
    if (GlobalConstant.RECORD_RELEASED.equals(maintForm.getStatus()) ) {
      ApplicationMessageList warningList = new ApplicationMessageList();
      WorkflowOperationManager workflowOperationManager = new WorkflowOperationManager(this.getSessionContainer(request), this.getConnection(request));
      ApplicationExceptionList exceptionList = workflowOperationManager.validateWorkflow((WorkflowRecord)form.getFormData(),warningList);
      if (exceptionList.getExceptionArray().length > 0) {
        maintForm.setStatus(GlobalConstant.RECORD_PENDING);
        exceptionList.throwException();
      }
      if(!Utility.isEmpty(warningList)&&!Utility.isEmpty(warningList.getActionMessageList())){
        //add the messages
        this.addMessages(request, warningList);
      }//add by TC FOR BUG-1630
      
      //if need special alt message,Please change it here. tc.add
      request.setAttribute(SPECIAL_MESSAGE,"workflow.message.record_release_success");
    }
    super.updateRecord(mapping, form, request, response);
    WorkflowRecord workflowRecord = (WorkflowRecord) form.getFormData();
    this.updateWorkflowRecordObjectLink(workflowRecord.getID(), workflowRecord.getWorkflowCategoryID(), categoryObjectID, rule, request);
    //  insert sub workflow for interruption header workflow is submitter(s)
    if (!Utility.isEmpty(maintForm.getInterruptSubmitter())
          || GlobalConstant.FALSE.equals(maintForm.getAllowInterrupt())) {
      wsManager.deleteWFInterruptUserActorByRecordID(new Integer(maintForm.getID()));
    }
    if (GlobalConstant.TRUE.equals(maintForm.getAllowInterrupt())) {
      this.insertInterruptWorkflowSubmitter(request, maintForm, new Integer(maintForm.getID()));
    } else {
      maintForm.setInterruptSubmitter(null);
    }
    if (!Utility.isEmpty(workflowRecord.getID()) && GlobalConstant.TRUE.equals(
        maintForm.getAllowInterrupt())) {
      setOldInterruptSubmitterAttribute(workflowRecord.getID(), request);
    }
  }

  public void selectRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    super.selectRecord(mapping, form, request, response);
    MaintWorkflowRecordForm maintForm = (MaintWorkflowRecordForm) form;
    WorkflowRecord workflowRecord = (WorkflowRecord) maintForm.getFormData();
    MtmWorkflowRecordObjectLinkDAObject linkDAO = new MtmWorkflowRecordObjectLinkDAObject(this.getSessionContainer(request), this.getConnection(request));
    MtmWorkflowInterruptUserActorDAObject interruptActorDAO = new MtmWorkflowInterruptUserActorDAObject(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStepOperationWarningMessageManager messageManager = new WorkflowStepOperationWarningMessageManager(this.getSessionContainer(request),this.getConnection(request));
    
    //* get any existing workflowRecordObjectLink
    Integer workflowRecordID = new Integer(-1);
    if (workflowRecord.getID()!=null) {
      workflowRecordID = workflowRecord.getID();
    }
    List objectLinkList = linkDAO.getListByWorkflowRecordID(workflowRecordID);
    String[] rule=new String[objectLinkList.size()], objectID=new String[objectLinkList.size()];
    for (int i=0; i<objectLinkList.size(); i++) {
      MtmWorkflowRecordObjectLink objLink = (MtmWorkflowRecordObjectLink) objectLinkList.get(i);
      objectID[i] = objLink.getObjectID().toString();
      if ("Y".equals(objLink.getWorkflowRule()) ) {
        rule[i] = objLink.getObjectID() + "_Y";
      } else {
        rule[i] = "";
      }
    }
    maintForm.setCategoryObjectID(objectID);
    maintForm.setRule(rule);
    // get the root ID
    Integer parentID = workflowRecord.getParentID();
    if(!Utility.isEmpty(parentID) && parentID.intValue() > 0 ){
      DmsDocumentDAObject dmsDocDAO = new DmsDocumentDAObject(this.getSessionContainer(request), this.getConnection(request));
      DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(this.getSessionContainer(request), this.getConnection(request));

      DmsDocument dms = (DmsDocument)dmsDocDAO.getObjectByID(parentID);
      String path = docRetrievalManager.getLocationPath(parentID);

      maintForm.setRootID(dms.getRootID());
      maintForm.setLocationPath(path);
    }
    // get current workflow Record is interrupt sub workflow submitters;
    if (!Utility.isEmpty(workflowRecord.getID())) {
      List interruptUserActorList = interruptActorDAO.getListByWorkflowRecordID(workflowRecord.getID());
      StringBuffer interruptSubmitterBuf = new StringBuffer();
      for (int j = 0; !Utility.isEmpty(interruptUserActorList) && j < interruptUserActorList.size(); j++) {
        MtmWorkflowInterruptUserActor interruptUserActor = (MtmWorkflowInterruptUserActor)interruptUserActorList.get(j);
        if (MtmWorkflowStepUserActor.ACTOR_TYPE_USER.equals(interruptUserActor.getActorType())) {
          interruptSubmitterBuf.append(MtmWorkflowStepUserActor.ACTOR_TYPE_USER + "_" + interruptUserActor.getActorID().toString() + ";");
        } else if (MtmWorkflowStepUserActor.ACTOR_TYPE_GROUP.equals(interruptUserActor.getActorType())) {
          interruptSubmitterBuf.append(MtmWorkflowStepUserActor.ACTOR_TYPE_GROUP + "_" + interruptUserActor.getActorID().toString() + ";");
        } else if (MtmWorkflowStepUserActor.ACTOR_TYPE_ROLE.equals(interruptUserActor.getActorType())) {
          interruptSubmitterBuf.append(MtmWorkflowStepUserActor.ACTOR_TYPE_ROLE + "_" + interruptUserActor.getActorID().toString() + ";");
        } else {
          interruptSubmitterBuf.append(interruptUserActor.getActorType() + "_" + interruptUserActor.getActorID().toString() + ";");
        }
      }
      //maintForm.setInterruptSubmitter(interruptSubmitterBuf.toString());
      request.setAttribute("oldInterruptSubmitter", interruptSubmitterBuf.toString());
    }
    
    this.addMessages(request, messageManager.createAllWorkflowStepWarningMessage(workflowRecord.getID()));
  }

  public void refreshFormData(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    MaintWorkflowRecordForm maintForm = (MaintWorkflowRecordForm) form;
    WorkflowRecord workflowRecord = (WorkflowRecord) maintForm.getFormData();

    maintForm.setFormData(workflowRecord);
    request.setAttribute("categoryObjectList", null);
    int workflowCategoryID = -1;
    if (workflowRecord.getWorkflowCategoryID()!=null) {
      workflowCategoryID = workflowRecord.getWorkflowCategoryID().intValue();
    }

    log.info("workflow category id: "+workflowCategoryID);
    if (   workflowCategoryID == Integer.parseInt(SystemWorkflowConstant.DMS_CREATE_PUBLIC_DOCUMENT)
        || workflowCategoryID == Integer.parseInt(SystemWorkflowConstant.DMS_CREATE_SCANNED_DOCUMENT)
        || workflowCategoryID == Integer.parseInt(SystemWorkflowConstant.DMS_CREATE_PAPER_DOCUMENT) ) { //* public folder
      DmsRootDAObject rootDAO = new DmsRootDAObject(this.getSessionContainer(request), this.getConnection(request));
      String orderBy="A.ROOT_NAME ASC";
      List rootList = rootDAO.getAllPublicRootListForWorkflow(orderBy);
      request.setAttribute("categoryObjectList", rootList);
    } else if (workflowCategoryID == Integer.parseInt(SystemWorkflowConstant.DMS_CREATE_PUBLIC_UDF_DOCUMENT)
            || workflowCategoryID == Integer.parseInt(SystemWorkflowConstant.DMS_CREATE_SCANNED_UDF_DOCUMENT)
            || workflowCategoryID == Integer.parseInt(SystemWorkflowConstant.DMS_CREATE_PAPER_UDF_DOCUMENT)  ) { //* document profile
      SysUserDefinedIndexDAObject profileDAO = new SysUserDefinedIndexDAObject(this.getSessionContainer(request), this.getConnection(request));
      String orderBy="A.USER_DEFINED_TYPE ASC";
      List profileList = profileDAO.getListByStatusForWorkflow(GlobalConstant.RECORD_STATUS_ACTIVE,orderBy);
      request.setAttribute("categoryObjectList", profileList);
    } else if (workflowCategoryID == Integer.parseInt(SystemWorkflowConstant.FMB_SUBMISSION_BY_FORM)) {
      FormRecordDAObject formDAO = new FormRecordDAObject(this.getSessionContainer(request), this.getConnection(request));
      String orderBy="A.TITLE,A.DESCRIPTION,A.FORM_VERSION ASC";
      List formRecordList = formDAO.getFormRecordByStatusExpiredForWorkflow(FormRecord.FORM_STATUS_RELEASED, GlobalConstant.TRUE,orderBy);
      request.setAttribute("categoryObjectList", formRecordList);
    } else if (workflowCategoryID == Integer.parseInt(SystemWorkflowConstant.FMB_SUBMISSION_BY_GROUP)) {
      FormGroupDAObject formGroupDAO = new FormGroupDAObject(this.getSessionContainer(request), this.getConnection(request));
      List formGroupList = formGroupDAO.getFullList();
      request.setAttribute("categoryObjectList", formGroupList);
    }else if (workflowCategoryID == Integer.parseInt(SystemWorkflowConstant.SUB_WORKFLOW_INTERRUPT)){ //* if sub_workflow_interrupt then delete the startworkflowStep's owner
      WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
      MtmWorkflowStepUserActorDAObject stepUserActorDAO = new MtmWorkflowStepUserActorDAObject(this.getSessionContainer(request), this.getConnection(request));
      if(workflowRecord!=null){
      Integer workflowStepID = stepDAO.getStepIDByWorkflowIDAndStepSeq(workflowRecord.getID(), new Integer(1));
      if(workflowStepID!=null){
        //delete startworkflowstep mtmfwstepuseractor record
        stepUserActorDAO.deleteListByWorkflowStepID(workflowStepID);
        this.commit(request);
      }
      }
    }
    
  }

  private void updateWorkflowRecordObjectLink(Integer workflowRecordID, Integer workflowCategoryID, String[] objectID, String[] rule, HttpServletRequest request) throws ApplicationException {
    MtmWorkflowRecordObjectLinkDAObject recordObjDAO = new MtmWorkflowRecordObjectLinkDAObject(this.getSessionContainer(request), this.getConnection(request));
    java.util.HashMap ruleMap = new java.util.HashMap();

    recordObjDAO.deleteListByWorkflowRecordID(workflowRecordID);

    for (int i=0; rule!=null && i<rule.length; i++) {
      ruleMap.put(rule[i].substring(0, rule[i].indexOf("_")), rule[i].substring(rule[i].indexOf("_")+1, rule[i].length()) );
    }

    for (int i=0; objectID!=null && i<objectID.length; i++) {
      MtmWorkflowRecordObjectLink objectLink = new MtmWorkflowRecordObjectLink();
      objectLink.setWorkflowRecordID(workflowRecordID);
      objectLink.setWorkflowCategoryID(workflowCategoryID);
      if (workflowCategoryID.equals(new Integer(SystemWorkflowConstant.DMS_CREATE_PUBLIC_DOCUMENT))
        || workflowCategoryID.equals(new Integer(SystemWorkflowConstant.DMS_CREATE_SCANNED_DOCUMENT))
        || workflowCategoryID.equals(new Integer(SystemWorkflowConstant.DMS_CREATE_PAPER_DOCUMENT))
        || workflowCategoryID.equals(new Integer(SystemWorkflowConstant.DMS_CHECKIN_PUBLIC_DOCUMENT))
        || workflowCategoryID.equals(new Integer(SystemWorkflowConstant.DMS_CHECKIN_SCANNED_DOCUMENT))) {
        objectLink.setObjectType(GlobalConstant.OBJECT_TYPE_DOCUMENT);

      } else if (workflowCategoryID.equals(new Integer(SystemWorkflowConstant.DMS_CREATE_PUBLIC_UDF_DOCUMENT))
        || workflowCategoryID.equals(new Integer(SystemWorkflowConstant.DMS_CREATE_SCANNED_UDF_DOCUMENT))
        || workflowCategoryID.equals(new Integer(SystemWorkflowConstant.DMS_CREATE_PAPER_UDF_DOCUMENT))
        || workflowCategoryID.equals(new Integer(SystemWorkflowConstant.DMS_CHECKIN_PUBLIC_UDF_DOCUMENT))
        || workflowCategoryID.equals(new Integer(SystemWorkflowConstant.DMS_CHECKIN_SCANNED_UDF_DOCUMENT))) {
        objectLink.setObjectType(GlobalConstant.OBJECT_TYPE_UDF);

      } else if (workflowCategoryID.equals(new Integer(SystemWorkflowConstant.FMB_SUBMISSION_BY_FORM))) {
        objectLink.setObjectType(GlobalConstant.OBJECT_TYPE_FORM);

      } else if (workflowCategoryID.equals(new Integer(SystemWorkflowConstant.FMB_SUBMISSION_BY_GROUP))) {
        objectLink.setObjectType(GlobalConstant.OBJECT_TYPE_FORMGROUP);
      }
      objectLink.setObjectID(TextUtility.parseIntegerObj(objectID[i]));
      objectLink.setWorkflowRule((String)ruleMap.get(objectID[i]));

      objectLink = (MtmWorkflowRecordObjectLink) recordObjDAO.insertObject(objectLink);
    }
  }

  private List getWorkflowRecordBySysWorkflowCategoryID(Integer sysWorkflowCategoryID, HttpServletRequest request) throws ApplicationException {
    SetupOptionWorkflowCategoryDAObject setupOptionWorkflowCategoryDAO = new SetupOptionWorkflowCategoryDAObject(this.getSessionContainer(request), this.getConnection(request));
    WorkflowRecordDAObject workflowRecordDAO = new WorkflowRecordDAObject(this.getSessionContainer(request), this.getConnection(request));
    List workflowRecordList = new ArrayList();
    try {
      List fullWorkflowRecordList = workflowRecordDAO.getLastBySysWorkflowCategoryID(sysWorkflowCategoryID);
      for (int i = 0; !Utility.isEmpty(fullWorkflowRecordList) && i < fullWorkflowRecordList.size(); i++) {
        WorkflowRecord workflowRecord =  (WorkflowRecord)fullWorkflowRecordList.get(i);
        String[] aOption = new String[2];
        aOption[1] = workflowRecord.getWorkflowCode() + "(" + (workflowRecord.getDescription()==null?"":workflowRecord.getDescription()) + "[" + workflowRecord.getWorkflowVersion() + "]" + ")";
        aOption[0] = workflowRecord.getID().toString();
        workflowRecordList.add(aOption);
      }
    } catch(ApplicationException ex){
      log.error(ex, ex);
    }
    return (workflowRecordList);
  }

  private void insertInterruptWorkflowSubmitter(
      HttpServletRequest request,
      AbstractActionForm form,
      Integer workflowRecordID) throws ApplicationException {
    MtmWorkflowInterruptUserActorDAObject interruptReqDAO = new MtmWorkflowInterruptUserActorDAObject(this.getSessionContainer(request), this.getConnection(request));
    MaintWorkflowRecordForm maintForm = (MaintWorkflowRecordForm)form;
    String interruptOwnerStr = maintForm.getInterruptSubmitter();
    if(!Utility.isEmpty(interruptOwnerStr)){
      String[] interruptOwnerArr = TextUtility.splitString(interruptOwnerStr, ";");
      for(int i=0; i<interruptOwnerArr.length; i++){
        String[] userOwnerType = TextUtility.splitString(interruptOwnerArr[i], "_");
        MtmWorkflowInterruptUserActor interruptUserActor = new MtmWorkflowInterruptUserActor();
        interruptUserActor.setWorkflowRecordID(workflowRecordID);
        interruptUserActor.setActorID(new Integer(userOwnerType[1]));
        interruptUserActor.setActorType(userOwnerType[0]);
        interruptReqDAO.insertObject(interruptUserActor);

      }
    }
  }


  public void deleteRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    super.deleteRecord(mapping, form, request, response);

    //Delete schedule job when a workflow record is deleted
    WorkflowScheduleTriggersDAObject triggerDAO = new WorkflowScheduleTriggersDAObject(this.getSessionContainer(request), this.getConnection(request));
    List triggerList = triggerDAO.getListByWorkflowRecordID(new Integer(form.getID()) );
    for (int i = 0; i < triggerList.size(); i++) {
      WorkflowScheduleTriggers trigger = (WorkflowScheduleTriggers)triggerList.get(i);

      //Cancel the Schedule Job
      try {
        log.debug("=== Cancel Schedule_Job ===");
        org.quartz.Scheduler sched = com.dcivision.framework.SchedulerFactory.getScheduler();

        log.debug("JOB:"+GlobalConstant.JOB_PREFIX_WORKFLOW_SCHEDULE + trigger.getID() +":" +
          GlobalConstant.JOB_PREFIX_WORKFLOW_SCHEDULE + "GROUP");

        sched.unscheduleJob( GlobalConstant.JOB_PREFIX_WORKFLOW_SCHEDULE + trigger.getID(),
          GlobalConstant.JOB_PREFIX_WORKFLOW_SCHEDULE + "GROUP" );
      } catch (SchedulerException se) {
        log.debug("=== Cancel Schedule_Job Fail ===");
        throw new ApplicationException(WorkflowErrorConstant.CANCEL_SCHEDULE_JOB_FAIL);
      }

    }
    //  added by nancy  
    WorkflowStepManager wsManager=new WorkflowStepManager(this.getSessionContainer(request), this.getConnection(request));
    wsManager.deleteStepByRecordID(new Integer(form.getID()));

    //end
    
  }

  private void deleteStep(AbstractActionForm form, HttpServletRequest request, boolean deleteAll) throws NumberFormatException, ApplicationException{
    MaintWorkflowRecordForm maintForm = (MaintWorkflowRecordForm) form;
    WorkflowOperationManager wfOperationManager = new WorkflowOperationManager(this.getSessionContainer(request),this.getConnection(request));
    WorkflowRecordDAObject tmpRecordDAO = new WorkflowRecordDAObject(this.getSessionContainer(request),this.getConnection(request));
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.getSessionContainer(request),this.getConnection(request));
    WorkflowStepOperationWarningMessageManager warningMessageManager = new WorkflowStepOperationWarningMessageManager(this.getSessionContainer(request),this.getConnection(request));
    
    String workflowRecordID = request.getParameter("workflowRecordID");
    if(!Utility.isEmpty(workflowRecordID)){
      maintForm.setID(workflowRecordID);
    }
    String workflowStepID = request.getParameter("currentWorkflowStepID");
    String connectedSubStepID=request.getParameter("connectedSubStepID");
    WorkflowStep workflowStep = (WorkflowStep)stepDAO.getObjectByID(Integer.valueOf(workflowStepID));
    
    if(!deleteAll){
      
      if(!Utility.isEmpty(workflowStepID)){
      //TC.ADD START
      boolean isLoopBack = false;
      if(!Utility.isEmpty(connectedSubStepID)){
        MtmWorkflowStepWorkflowStepDAObject stepStepDAO = new MtmWorkflowStepWorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
        MtmWorkflowStepWorkflowStep tmpStepStep = (MtmWorkflowStepWorkflowStep) stepStepDAO.getParentStepToChildStepRecord(null,new Integer(workflowStepID),null, new Integer(connectedSubStepID));
        isLoopBack=(MtmWorkflowStepWorkflowStep.LOOP_BACK_YES.equals(tmpStepStep.getLoopBack()));
      }
      //if is loopBack step,than delete it : is the simple way to deal with it
      //if want to route to loopback Step,should check if this banch ahead did not contains this Step...For BUG-121
      //TC.END  
      if(!Utility.isEmpty(connectedSubStepID)&&!isLoopBack ){//&& !(childStepID.toString()).equals(connectedSubStepID)){
        wfOperationManager.deleteSingleWorkflowStep(new Integer(workflowStepID),new Integer(connectedSubStepID));

      }else{
        wfOperationManager.deleteSingleWorkflowStep(new Integer(workflowStepID));
      }
     }
    }else{  
      String parentStepID = request.getParameter("parentStepID");
      if(!Utility.isEmpty(workflowStepID)){
        wfOperationManager.deleteWorkflowSteps(new Integer(workflowStepID),new Integer(parentStepID));
      } 
    }
    
    //update workflow record update_info
    if(!Utility.isEmpty(workflowRecordID)){
      tmpRecordDAO.updateObject(tmpRecordDAO.getObjectByID(Integer.valueOf(workflowRecordID)));
    }
    
    this.addMessages(request, warningMessageManager.createWorkflowStepDeleteWarningMessage(workflowStep)); 
    
  }

  /**
   * set oldInterruptSubmitter when call updateRecord method.
   * @param workflowRecordID workflowRecordID.
   * @param request HttpServletRequest.
   * @throws ApplicationException ApplicationException.
   */
  public void setOldInterruptSubmitterAttribute(Integer workflowRecordID, HttpServletRequest request)
   throws ApplicationException {
    MtmWorkflowInterruptUserActorDAObject interruptActorDAO = new MtmWorkflowInterruptUserActorDAObject(this.getSessionContainer(request),
        this.getConnection(request));
    List interruptUserActorList = interruptActorDAO.getListByWorkflowRecordID(workflowRecordID);
    StringBuffer interruptSubmitterBuf = new StringBuffer();
    for (int j = 0; !Utility.isEmpty(interruptUserActorList) && j < interruptUserActorList.size(); j++) {
      MtmWorkflowInterruptUserActor interruptUserActor = (MtmWorkflowInterruptUserActor) interruptUserActorList.get(j);
      if (MtmWorkflowStepUserActor.ACTOR_TYPE_USER.equals(interruptUserActor.getActorType())) {
        interruptSubmitterBuf.append(MtmWorkflowStepUserActor.ACTOR_TYPE_USER + "_" + interruptUserActor.getActorID().toString() + ";");
      } else if (MtmWorkflowStepUserActor.ACTOR_TYPE_GROUP.equals(interruptUserActor.getActorType())) {
        interruptSubmitterBuf.append(MtmWorkflowStepUserActor.ACTOR_TYPE_GROUP + "_" + interruptUserActor.getActorID().toString() + ";");
      } else if (MtmWorkflowStepUserActor.ACTOR_TYPE_ROLE.equals(interruptUserActor.getActorType())) {
        interruptSubmitterBuf.append(MtmWorkflowStepUserActor.ACTOR_TYPE_ROLE + "_" + interruptUserActor.getActorID().toString() + ";");
      } else {
        interruptSubmitterBuf.append(interruptUserActor.getActorType() + "_" + interruptUserActor.getActorID().toString() + ";");
      }
    }
    request.setAttribute("oldInterruptSubmitter", interruptSubmitterBuf.toString());
  }
}